#ifndef __LIST_HPP__
#define __LIST_HPP__

#include<iostream> 
#include "list_node.hpp"

template <typename T>
class LinkList_Head{
private:
    int element_size;
    LinkList_Node<T> *head;
    LinkList_Node<T> *tail;


public:
    LinkList_Head(){
        this->element_size=0;
        this->head=nullptr;
        this->tail=nullptr;
    }

    LinkList_Head(int num);
    explicit LinkList_Head(const LinkList_Head<T>& other);
    ~LinkList_Head();
    
    void node_push_back(const T& element_data);
    void node_push_head(const T& element_data);
    void Insert_SignleNode(int pos,const T& element_data);
    void print();
    LinkList_Node<T> *return_head_ptr(){
        return this->head;
    } 

    LinkList_Head<T>& operator=(LinkList_Head<T>& other);
    const T& operator[](int i);   
};

template <typename T>
LinkList_Head<T>::LinkList_Head(int num){
        this->element_size=num;
        this->head=nullptr;
        this->tail=nullptr;
}

template <typename T>
LinkList_Head<T>::LinkList_Head(const LinkList_Head<T>& other){
    this->element_size=other.element_size;
    this->head=other.head;
    this->tail=other.tail;
}

template <typename T>
void LinkList_Head<T>::node_push_back(const T& element_data){
    LinkList_Node<T> *new_node=new LinkList_Node<T>(element_data);
    LinkList_Node<T> *now;
    if(this->element_size==0){
        this->head=new_node;
        this->tail=new_node;
    }else{
        now=this->tail;
        this->tail=new_node;
        now->next=new_node;
    }
    this->element_size++;
}

template <typename T>
void LinkList_Head<T>::node_push_head(const T& element_data){
    LinkList_Node<T> *new_node=new LinkList_Node<T>(element_data);
    LinkList_Node<T> *now; 

    if(this->element_size==0){
        this->head=new_node;
        this->tail=new_node;
    }else{
        now=this->head;
        this->head=new_node;
       new_node->next=new_node;
    }
    this->element_size++;  
}

template <typename T>
void LinkList_Head<T>::print(){
    LinkList_Node<T> *now=this->head;
    std::cout<<"link element size:"<<this->element_size<<" element:";
    while(now!=nullptr){
        std::cout<<now->element_data<<" ";
        now=now->next;
    }
    std::cout<<std::endl;
}

template <typename T>
void LinkList_Head<T>::Insert_SignleNode(int pos,const T& element_data){
    if(this->element_size==0 || pos>this->element_size){
        return ;
    }
    int couter=0;
    LinkList_Node<T> *now=this->head;
    while(now!=nullptr){
        if(couter+1==pos){
            break;
        }
        now=now->next;
        couter++;
    }
    LinkList_Node<T> *new_node=new LinkList_Node<T>(element_data);
    if(pos==0){
        now=this->head;
        this->head=new_node;
        new_node->next=now;
    }else{
        LinkList_Node<T> *node_next=now->next;
        now->next=new_node;
        new_node->next=node_next;
    }
    this->element_size++;
}

template <typename T>
LinkList_Head<T>::~LinkList_Head(){
    
    if(this->element_size!=0){
        LinkList_Node<T> *now=this->head;
        LinkList_Node<T> *tmp=this->head;
        
        for(int i = 0; i < this->element_size;i++){
            tmp=tmp->next;
            delete now;
            now=tmp;
        }
        this->element_size=0;
    }
}

template <typename T>
LinkList_Head<T>& LinkList_Head<T>::operator=(LinkList_Head<T>& other){
   if(this!=&other){
        if(this->head!=nullptr && this->tail!=nullptr){
            LinkList_Node<T> *now=this->head;
            LinkList_Node<T> *tmp=this->head;
        
            for(int i = 0; i < this->element_size;i++){
                tmp=tmp->next;
                delete now;
                now=tmp;
            }
        }

        
        this->head=new LinkList_Node<T>(other.head->element_data);
        LinkList_Node<T> *now=other.head->next;
        LinkList_Node<T> *prv=this->head;
        while (now!=nullptr){
            LinkList_Node<T> *new_node=new LinkList_Node<T>(now->element_data);
            prv->next=new_node;
            prv=prv->next;
            now=now->next;
        }
        this->tail=prv;
        this->element_size=other.element_size;
   }
   return *this;
}

template <typename T>
const T& LinkList_Head<T>::operator[](int i){
    int pos=0;
    LinkList_Node<T> *now=this->head;
    while(now!=nullptr){
        if(pos==i){
            break;
        }
        now=now->next;
        pos++;
    }
    return now->element_data;
}
template <typename T>
std::ostream& operator<<(std::ostream& os,LinkList_Head<T>& list_head){
    LinkList_Node<T> *now=list_head.return_head_ptr();
    while(now!=nullptr){
        std::cout<<now->element_data<<" ";
        now=now->next;
    }   
    return os;
}

#endif
